#include "factory.h"

int main(int argc,char** argv)
{
    if(argc!=3)
    {
        printf("/thread_pool_server IP PORT\n");
        return -1;
    }
    ARGS_CHECK(argc,3);
    int sfd;
    
    int flag=0;//在输入用户名和密码时判断是否与服务器端连接的标志
    int ready_fd_num,i,j,ret,cn;
    
    char *crpwd;
    int cor;
    char c_cmd[128]={0};
    char info[128]={0};
    char token[128];
    Factory_t f;//主数据结构
    int thread_num=THREAD_NUM;//子线程数量
    int capacity=CAPACITY;//队列容量
    factory_init(&f,thread_num,capacity);//线程池初始化
    factory_start(&f,thread_num);//启动线程池
    Client_State_t* pnew;
    train_state_t* ct;
    usraddr usr;
    bzero(&ct,sizeof(train_state_t));
    pQue_t pq=&f.que;//让一个队列指针指向队列
    struct epoll_event evs[2];
    //epoll注册监控sfd,STDIN_FILENO
    int epfd=epoll_create(1);
    epoll_add(epfd,STDIN_FILENO);
reconnect:
    sfd=socket(AF_INET,SOCK_STREAM,0);//初始化一个网络描述符，对应了一个缓冲区
    ERROR_CHECK(sfd,-1,"socket");
    printf("sfd=%d\n",sfd);
    struct sockaddr_in ser_addr;
    bzero(&ser_addr,sizeof(ser_addr));//清空
    ser_addr.sin_family=AF_INET;//代表要进行ipv4通信
    ser_addr.sin_addr.s_addr=inet_addr(argv[1]);//把ip的点分十进制转为网络字节序
    ser_addr.sin_port=htons(atoi(argv[2]));//把端口转为网络字节序
    epoll_add(epfd,sfd);
    char mutex_buf[5];//存当前login锁的状态
    bzero(mutex_buf,5);
    char one_buf[5]="1";//1代表不能登录
    char zero_buf[5]="0";//0代表能登录
    int mutex=open("login_mutex",O_RDWR);
    //客户端去连接服务器端
    ret=connect(sfd,(struct sockaddr *)&ser_addr,sizeof(ser_addr));
    ERROR_CHECK(ret,-1,"connect");
    if(-1==ret)
    {
        printf("Connect fail!\n");
    }
    //检查login锁，若为0则进行登录，为1则等待
    if(ret!=-1)
    {
        check_login_mutex1(mutex,mutex_buf,one_buf,zero_buf);
    }
fail_label:
    bzero(&ct,sizeof(ct));
    bzero(&token,sizeof(token));
    print_login();//打印登录界面
Error_command:
    printf("login or register or quit:\n");
    scanf("%s",ct->cmd);
    ct->cmd_type = cmd_type_func(ct->cmd);
    ct->data_len=sizeof(train_state_t);
    ret=send_n(sfd,&ct->data_len,sizeof(int)); 
    SELFFUNC_ERR_CHECK(ret,"send_n");
    ret=send_n(sfd,&ct,4+ct->data_len);
    SELFFUNC_ERR_CHECK(ret,"send_n");
    if(ct->cmd_type==LOGIN)
    {
        ret=client_login(sfd,token,usr);
        if(ret==-1)//登陆失败
        {
            goto fail_label;
        }
    }
    else if(ct->cmd_type==REGISTER)
    {
        ret=client_register(sfd,token,usr);
        if(ret==-1)//注册失败
        {
            goto fail_label;    
        }
    }
    else if(ct->cmd_type==QUIT)
    {

        ct->data_len=sizeof(train_state_t);
        ret=send_n(sfd,&ct->data_len,sizeof(int));//发送QUIT命令长度
        ERROR_CHECK(ret,-1,"send_n");
        ret=send_n(sfd,&ct,4+ct->data_len);//发送QUIT命令内容
        ERROR_CHECK(ret,-1,"send_n");
        close(sfd);
        printf("Quit the success\n");
        lseek(mutex,0,SEEK_SET);
        ret=write(mutex,zero_buf,1);//解login锁
        return -1;
    }
    else if(ct->cmd_type==TOKEN)
    {
        ret=client_token(sfd,ct,token);
        if(-1==ret)//token验证失败
        {
            printf("Validation fail!\n");
            goto fail_label;
        }
    }
    else{
        bzero(&ct,sizeof(train_state_t));
        ct->cmd_type=FAULTY;
        ct->data_len=sizeof(train_state_t);
        ret=send_n(sfd,&ct->data_len,sizeof(int));//发送命令长度
        ERROR_CHECK(ret,-1,"send_n");
        ret=send_n(sfd,&ct,4+ct->data_len);//发送命令内容
        ERROR_CHECK(ret,-1,"send_n");
        goto Error_command;
    }
    lseek(mutex,0,SEEK_SET);
    ret=write(mutex,zero_buf,1);//解login锁
    close(mutex);
    while(1)
    {
        ready_fd_num=epoll_wait(epfd,evs,2,-1);//等待描述符就绪，哪个描述符就绪，epoll就会返回
        for(i=0;i<ready_fd_num;i++)
        {
            if(evs[i].data.fd==STDIN_FILENO)//标准输入可读
            {
                bzero(&ct,sizeof(train_state_t));
                scanf("%s %s",ct->cmd,ct->file_name);
                ct->cmd_type = cmd_type_func(ct->cmd);
                if (ct->cmd_type<1|| ct->cmd_type>6)
                {
                    printf("Invalid input\n");
                    continue;
                }
                if(ct->cmd_type==LS||ct->cmd_type==CD||ct->cmd_type==REMOVE||ct->cmd_type==PWD)
                {
                    ct->data_len=sizeof(train_state_t);
                    ret=send_n(sfd,&ct->data_len,sizeof(int)); 
                    SELFFUNC_ERR_CHECK(ret,"send_n");
                    ret=send_n(sfd,&ct,4+ct->data_len);
                    SELFFUNC_ERR_CHECK(ret,"send_n");
                }
                else{
                    printf("thread start!\n");
                    pnew=(Client_State_t*)calloc(1,sizeof(Client_State_t));//申请空间
                    //pnew放入队列
                    pnew->sfd=sfd;
                    strcpy(pnew->ip,argv[1]);
                    strcpy(pnew->port,argv[2]);
                    strcpy(pnew->token,token);
                    pthread_mutex_lock(&pq->mutex);//加锁
                    que_set(pq,pnew);//放入队列
                    pthread_mutex_unlock(&pq->mutex);//解锁
                    pthread_cond_signal(&f.cond);//使条件成立
                }
            }
            if(evs[i].data.fd==sfd)//如果sfd可读
            {
                int c_cmd_len;
                bzero(info,sizeof(info));
                ret=recv_n(sfd,&c_cmd_len,sizeof(int));//接收服务器端发送的火车头
                SELFFUNC_ERR_CHECK(ret,"recv_n");
                ret=recv_n(sfd,info,c_cmd_len);//接收服务器端发送的火车厢
                SELFFUNC_ERR_CHECK(ret,"recv_n");
                printf("%s\n",info);
            }    
        }
    }
    close(sfd);
    return 0;
}